package com.chenfan.ccp.plug.mybatis.util;

import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class JavaDocReader {
    private static final String DOC_START = "/**";
    private static final String DOC_END = "*/";
    private static final String IMPORT_SYMBOL = "import ";


    /**
     * hashMap map转json
     *
     * @param map
     * @return
     */

    private static String map2Json(Map<String, String> map) {
        StringBuilder stringBuilder = new StringBuilder("{");
        if (map == null || map.isEmpty()) {
            stringBuilder.append("}");
            return stringBuilder.toString();
        } else {

            for (Map.Entry<String, String> entry : map.entrySet()) {
                stringBuilder.append("'").append(entry.getKey()).append("'").append(":").append("'").append(entry.getValue()).append("'").append(",");
            }
            stringBuilder.insert(stringBuilder.length() - 1, "}");

            return stringBuilder.substring(0, stringBuilder.length() - 1);
        }
    }

    /**
     * 根据字符串获取java的说明
     *
     * @param text 字符串内容
     * @return
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     */
    private static String getJavaDocExplain(String text) {
        Pattern pattern = Pattern.compile("(.*)\\{@(link|linkplain)(.*)}");
        Matcher matcher = pattern.matcher(text);

        try {
            if (matcher.find()) {
                StringBuilder enumsLinkBuilder = new StringBuilder();
                Class<?> findClass = Class.forName(matcher.group(3).trim());

                if (findClass.isEnum()) {

                    //枚举
                    Object[] enumConstants = findClass.getEnumConstants();
                    for (Object enums : enumConstants) {
                        StringBuilder enumsFileBuilder = new StringBuilder();
                        for (Field field : enums.getClass().getDeclaredFields()) {
                            if (!(field.isEnumConstant() || field.getName().equals("$VALUES"))) {
                                field.setAccessible(true);
                                if (enumsFileBuilder.length() != 0) {
                                    enumsFileBuilder.append(":");
                                }
                                enumsFileBuilder.append(field.get(enums));

                            }


                        }
                        if (enumsFileBuilder.length() == 0) {
                            continue;
                        }
                        //如果没有多个构造参数说明，那么把枚举的定义加上
                        if (!enumsFileBuilder.toString().contains(":")) {
                            enumsFileBuilder.insert(0, enums + ":");
                        }
                        if (enumsLinkBuilder.length() != 0) {
                            enumsLinkBuilder.append(",");
                        }

                        enumsLinkBuilder.append(enumsFileBuilder);


                    }
                } else {

                    for (Field field : findClass.getDeclaredFields()) {

                        if (Modifier.isStatic(field.getModifiers())) {
                            field.setAccessible(true);
                            if (enumsLinkBuilder.length() != 0) {
                                enumsLinkBuilder.append(",");
                            }
                            enumsLinkBuilder.append(field.getName());
                            enumsLinkBuilder.append(":");
                            enumsLinkBuilder.append(field.get(findClass));


                        }
                    }


                }
                enumsLinkBuilder.insert(0, matcher.group(1));
                return enumsLinkBuilder.toString();
            }
        } catch (Exception e) {

        }
        return text;

    }


    public static String read(Class aClass) {

        String resultJson = "";

        try {

//            Map<String, Object> scanner = Scanner.scanner(aClass.getPackage().getName(), null);
            Map<String, Object> scanner = new HashMap<>();

            if (scanner == null) {
                return resultJson;
            }
            Object result = scanner.get("scanner:file:key");
            if (result == null) {
                return resultJson;
            }
            List<File> resultFile = (List<File>) result;
            Map<String, String> commitMap = new HashMap<>();

            for (File file : resultFile) {
                if (!file.getName().equals(aClass.getSimpleName() + ".java")) {
                    continue;
                }
                StringBuilder commitBuilder = new StringBuilder();
                AtomicBoolean commitFlag = new AtomicBoolean(false);

                List<String> collect = new BufferedReader(new FileReader(file)).lines().collect(Collectors.toList());

                Map<String, String> importPackageNameMap = new HashMap<>();

                for (String line : collect) {


                    if (line.trim().startsWith(DOC_START)) {

                        commitFlag.set(true);

                    } else if (line.trim().endsWith(DOC_END)) {

                        commitFlag.set(false);
                        continue;

                    } else if (line.trim().startsWith(IMPORT_SYMBOL)) {

                        try {

                            //第一个空格
                            String importStr = line.trim().substring(line.trim().indexOf(" "))
                                    .split(";")[0];
                            if (importStr.endsWith("*")) {
                                importStr = importStr.split("\\*")[0];
                            }

                            importStr = importStr.replaceAll("\\s+", "");

                            //排除java自带的类
                            if (importStr.startsWith("java")) {
                                continue;
                            }

                            importPackageNameMap.put(importStr.substring(importStr.lastIndexOf(".") + 1),
                                    importStr);

                        } catch (Exception e) {

                        }

                    }
                    if (commitFlag.get()) {
                        commitBuilder.append(line);
                    } else {
                        if (!line.trim().isEmpty() && commitBuilder.length() != 0) {

                            //过滤注解和注释
                            if (line.trim().startsWith("@") || line.trim().startsWith("//")) {
                                continue;
                            }

                            //排除class
                            if (!line.trim().startsWith("public class")) {
                                //这里增加复合类型的输入
                                char[] chars = line.trim().toCharArray();
                                int charsLength = chars.length;
                                //找出第一个类名的开始位置
                                for (int k = 0; k < charsLength; k++) {
                                    if (Character.isUpperCase(chars[k])) {
                                        charsLength = k;
                                        break;
                                    }
                                }
                                //查找出
                                if (charsLength == chars.length) {
                                    continue;
                                }

                                //获取导入包的包名
                                String packageName = line.trim().substring(charsLength).split(" ")[0];

                                //增加集合类型的适配
                                if (packageName.indexOf("<") > 0) {
                                    packageName = packageName
                                            .substring(packageName.indexOf("<") + 1, packageName.lastIndexOf(">"));
                                    //Map类型目前指解析value
                                    if (packageName.contains(",")) {
                                        packageName = packageName.split(",")[1];
                                    }
                                }


                                String importPack = importPackageNameMap.get(packageName);
                                String docKey = line.trim().substring(line.trim().lastIndexOf(" "),
                                        line.trim().length() - 1);
                                //如果查找不到，尝试同包或者*的包名
                                if (StringUtils.isEmpty(importPack)) {
                                    try {
                                        //先获取*包
                                        Class<?> subClass = Class.forName(importPackageNameMap.get("") + packageName);

                                        //递归进行解析
                                        commitMap.put(docKey, read(subClass));
                                        continue;
                                    } catch (ClassNotFoundException ex) {
                                        try {
                                            Class<?> subClass = Class.forName(aClass.getPackage()
                                                    .getName() + "." + packageName);
                                            //递归进行解析
                                            commitMap.put(docKey, read(subClass));
                                            continue;
                                        } catch (ClassNotFoundException subEx) {

                                        }

                                    }
                                } else {
                                    try {
                                        //直接解析包即可
                                        Class<?> subClass = Class.forName(importPack);
                                        //递归进行解析
                                        commitMap.put(docKey, read(subClass));
                                        continue;
                                    } catch (ClassNotFoundException ex) {

                                    }


                                }

                                commitMap.put(docKey, getJavaDocExplain(commitBuilder.toString().replaceAll("/|\\*", "").trim()));
                            }

                            commitBuilder.delete(0, commitBuilder.length());
                        }
                    }
                }
            }

            resultJson = map2Json(commitMap);

        } catch (Exception e) {

        }

        return resultJson;


    }


}
